package com.ben.chatroom.distribute;

import com.ben.chatroom.common.constants.ServerConstants;
import com.ben.chatroom.common.zk.CuratorZKclient;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.atomic.AtomicValue;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.retry.RetryNTimes;

/**
 * 分布式计数器
 *
 * @author huangyijun
 */
@Slf4j
public class OnlineCounter {

  private Long curValue;
  private CuratorFramework client;
  private static OnlineCounter instance;
  private DistributedAtomicLong distributedAtomicLong;
  private final static String PATH = ServerConstants.COUNTER_PATH;

  private OnlineCounter() {
  }

  public static OnlineCounter getInstance() {
    if(null == instance) {
      instance = new OnlineCounter();
      instance.client = CuratorZKclient.getSingleton().getClient();
      instance.init();
    }

    return instance;
  }

  /**
   * 分布式计数器，失败时重试10，每次间隔30毫秒
   */
  private void init() {
    distributedAtomicLong = new DistributedAtomicLong(client, PATH, new RetryNTimes(10, 30));
  }

  /**
   * 增加计数
   */
  public Boolean increment() {
    boolean res = false;
    AtomicValue<Long> val;
    try {
      val = distributedAtomicLong.increment();
      res = val.succeeded();
      log.info("old cnt:" + val.preValue() + "  new cnt : " + val.postValue() + "  result: " + val.succeeded());
      curValue = val.postValue();
    }
    catch(Exception e) {
      log.error(e.getMessage());
    }

    return res;
  }

  public boolean decrement() {
    boolean res = false;
    AtomicValue<Long> val;
    try {
      val = distributedAtomicLong.decrement();
      res = val.succeeded();
      log.info("old cnt:" + val.preValue() + "  new cnt : " + val.postValue() + "  result: " + val.succeeded());
      curValue = val.postValue();
    }
    catch(Exception e) {
      log.error(e.getMessage());
    }

    return res;
  }
}
